package com.luckynote.common.base.dubbo;

import com.caucho.services.server.GenericService;
import com.luckynote.common.base.exception.BizException;
import com.luckynote.common.base.result.ExecuteResult;
import com.luckynote.common.base.result.ResponseInfo;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.common.extension.Adaptive;
import org.apache.dubbo.remoting.p2p.Group;
import org.apache.dubbo.rpc.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;

/**
 * <pre>
 * *********************************************
 * Copyright LUCKY-NOTE.
 * All rights reserved.
 * ****************************************************
 *  Version       Date         Author            Desc
 *    v1.0       2019/7/1      bingo        Dubbo统一异常过滤器
 * ****************************************************
 * </pre>
 */
@Activate(group = CommonConstants.PROVIDER)
public class ExceptionHandlerFilter implements Filter {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {

        Result result = invoker.invoke(invocation);

        if (!result.hasException() || GenericService.class == invoker.getInterface()) {
            return result;
        }

        try {
            //获取返回的异常对象
            Throwable exception = result.getException();
            //获取接口Class对象
            Class<?> anInterface = invocation.getInvoker().getInterface();
            //获取调用的方法
            Method method = anInterface.getMethod(invocation.getMethodName(), invocation.getParameterTypes());
            //获取方法的返回类型
            Class<?> returnType = method.getReturnType();
            //是ExecuteResult的子类
            boolean isExecuteResult = ExecuteResult.class.isAssignableFrom(returnType);
            if (isExecuteResult) {
                ResponseInfo responseInfo;
                //该异常是BizException类型实例
                if (exception instanceof BizException) {
                    BizException bizException = (BizException) exception;
                    responseInfo = bizException.getInfo();
                    logger.error(bizException.getInfo().toString(), bizException);
                } else {
                    responseInfo = new ResponseInfo("400", "系统异常", exception.toString());
                    logger.error(exception.getMessage(), exception);
                }
                ExecuteResult executeResult = (ExecuteResult) returnType.newInstance();
                executeResult.setResponseInfo(responseInfo);
                executeResult.setSuccessful(false);
                //重新包装后抛出
                return AsyncRpcResult.newDefaultAsyncResult(executeResult, invocation);
            }
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException e) {
            logger.error(e.getMessage(), e);
        }
        return result;
    }
}
